﻿using System;
using System.Collections.Generic;
using System.Text;
using UnitLibrary.GameObjects;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using UnitLibrary.GameObjects.Units;
using UnitLibrary.GameObjects.UnitReaders;
using UnitLibrary.Utility;

namespace UnitLibrary.Managers
{
    /// <summary>
    /// 
    /// </summary>
    public class PlayerM: Manager, IManager
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="game"></param>
        /// <param name="components"></param>
        public PlayerM(Game game, ComponentM components)
            : base(game, components)
        {
            _player = new Player();
            
        }
        

        /// <summary>
        /// Player object that is in the physics engine, and can be loaded from the content pipeline
        /// </summary>
        private Player _player;

        private double _fireTimer = 0;

        private double _attackRate;

        private Vector2 _lastMoveDirection = Vector2.Zero;
        /// <summary>
        /// Publicly exposed player for conveince
        /// </summary>
        public Player Player
        {
            get { return _player; }
        }

        /// <summary>
        /// Load the player
        /// </summary>
        public void LoadContent()
        {
            Player playa = ObjectSerialization<Player>.Deserialize("Player");
            _player.Create(playa, _components, new Vector2(250, 250), Vector2.Zero, true);
            this._attackRate = _components.bulletManager2.GetDefinition("Default").AttackRate;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="gameTime"></param>
        public void Update(GameTime gameTime)
        {
            _fireTimer += gameTime.ElapsedGameTime.Milliseconds;
            //Handle input for the player
            HandleInput();
            _player.Update(gameTime);
        }

        /// <summary>
        /// Handle input
        /// </summary>
        private void HandleInput()
        {
            //Directly manipulate the move direction            
            _player.MoveDirection = MovePlayer();
            if (ButtonState.Pressed == _components.inputHelper.CurrentMouseState.LeftButton)
            {
                if (_fireTimer > this._attackRate)
                {
                    _fireTimer = 0;
                    Vector2 fireDirection;
                    Vector2 mouseLocation;
                    mouseLocation.X = _components.inputHelper.CurrentMouseState.X;
                    mouseLocation.Y = _components.inputHelper.CurrentMouseState.Y;
                    //The player position is located in the world
                    //The mouse location is based on the screen
                    //Must translate from screen to world
                    mouseLocation = _components.cameraManager.ToWorldLocation(mouseLocation);
                    fireDirection = Vector2.Subtract(mouseLocation, _player.Position);
                    fireDirection.Normalize();
                    _components.CreateUnit(UnitID.Bullet, _player.CurrentWeapon, _player.Position, fireDirection);
                }
            }
            if (_components.inputHelper.IsNewPress(MouseButtons.RightButton))
            {
                if (_player.Points > _player.CurrentSentryCost)
                {
                    _player.PointAdjust(-20);
                    _components.CreateUnit(UnitID.Tower, _player.CurrentSentry, _components.cameraManager.ToWorldLocation(_components.inputHelper.MousePosition), Vector2.Zero);
                }
            }
        }

        /// <summary>
        /// Based on user input, move the player in a specific direction
        /// </summary>
        private Vector2 MovePlayer()
        {
            
            bool isMoved = false;
            Vector2 moveDirection = Vector2.Zero;
            //Move left
            if (_components.inputHelper.CurrentKeyboardState.IsKeyDown(Keys.A) 
                || _components.inputHelper.CurrentKeyboardState.IsKeyDown(Keys.Left))
            {
                moveDirection.X += -1f;
                isMoved = true;
            }

            //Move right
            if (_components.inputHelper.CurrentKeyboardState.IsKeyDown(Keys.D)
                || _components.inputHelper.CurrentKeyboardState.IsKeyDown(Keys.Right))
            {
                moveDirection.X += 1f;
                isMoved = true;
            }

            //Move up
            if (_components.inputHelper.CurrentKeyboardState.IsKeyDown(Keys.W)
                || _components.inputHelper.CurrentKeyboardState.IsKeyDown(Keys.Up))
            {
                moveDirection.Y += -1f;
                isMoved = true;
            }

            //Move down
            if (_components.inputHelper.CurrentKeyboardState.IsKeyDown(Keys.S)
                || _components.inputHelper.CurrentKeyboardState.IsKeyDown(Keys.Down))
            {
                moveDirection.Y += +1f;
                isMoved = true;
            }

            if (isMoved)
            {
                _lastMoveDirection = moveDirection;
                return moveDirection;
            }
            else
                _player.MoveDirection = _lastMoveDirection;
            return moveDirection;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="gameTime"></param>
       public void Draw(SpriteBatch _spriteBatch)
        {
            _player.Draw(_spriteBatch);
        }
    }
}
